﻿namespace Bowlus.Common
{
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.IO;
    using Microsoft.WindowsAzure;
    using Microsoft.WindowsAzure.ServiceRuntime;
    using Microsoft.WindowsAzure.StorageClient;
    using System.Linq;

    // TODO: Implement cache features
    public sealed class StorageAppRepository : IAppRepository
    {
        private readonly CloudBlobContainer appContainer;
        private readonly CloudBlobContainer customizationContainer;

        public StorageAppRepository(string configuration, string zipLibraryPath)
            : this(configuration)
        {
            // Initialize 7Zip Library Wrapper
            SevenZip.SevenZipBase.SetLibraryPath(zipLibraryPath);
        }

        public StorageAppRepository(string configuration)
        {
            this.appContainer = CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue(configuration)).CreateCloudBlobClient().GetContainerReference(Settings.AppContainer);
            this.customizationContainer = CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue(configuration)).CreateCloudBlobClient().GetContainerReference(Settings.CustomizationContainer);
        }

        // Used for uploading a new application
        public void Upload(string name, MemoryStream stream)
        {
            // TODO: implement this
        }

        public Collection<string> GetCustomizationList(string appName)
        {
            var blobs = this.customizationContainer.ListBlobs();
            var filteredBlobs = (from b in blobs
                                 where b.Uri.AbsolutePath.IndexOf(appName, StringComparison.InvariantCultureIgnoreCase) >= 0
                                 select Path.GetFileName(b.Uri.ToString())).ToArray();

            return new Collection<string>(filteredBlobs);
        }

        public Collection<string> GetAppList()
        {
            var blobs = this.appContainer.ListBlobs();

            // Create a dictionary for dropdown list
            var dict = blobs.Select(app => Path.GetFileName(app.Uri.ToString())).ToDictionary(s => s);

            var appList = new Collection<string>();
            foreach (var item in dict)
            {
                appList.Add(item.Value);
            }

            return appList;
        }

        public MemoryStream DownloadApp(string name)
        {
            var blob = this.appContainer.GetBlobReference(name);
            MemoryStream st = new MemoryStream();
            blob.DownloadToStream(st);

            return st;
        }

        public MemoryStream GetTenantCustomization(string tenantid)
        {
            return new MemoryStream();
        }

        public void ExtractTenantApplication(TenantDeployment tenantDeployment, string destination)
        {
            var blob = this.appContainer.GetBlobReference(tenantDeployment.Application);

            using (var stream = new MemoryStream())
            {
                blob.DownloadToStream(stream);

                var extractor = new SevenZip.SevenZipExtractor(stream);
                extractor.ExtractArchive(destination);
            }

            if (tenantDeployment.IncludesCustomizations)
            {
                writeCustomizationsTo(tenantDeployment, destination);
            }
        }

        private void writeCustomizationsTo(TenantDeployment td, string destination)
        {
            IEnumerable<string> customizations = td.GetCustomizations();
            foreach (var item in customizations)
            {
                var blob = this.customizationContainer.GetBlobReference(item);

                using (var stream = new MemoryStream())
                {
                    blob.DownloadToStream(stream);

                    var extractor = new SevenZip.SevenZipExtractor(stream);
                    extractor.ExtractArchive(destination);
                }
            }
        }
    }
}
